home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / CRYP60.ZIP / CRYN.C < prev    next >
C/C++ Source or Header  |  1992-11-15  |  16KB  |  580 lines

  1. #include <stdlib.h> /* defines exit() and malloc()                       */
  2. #include <string.h> /* defines strlen etc.                               */
  3. #include <stdio.h>  /* defines NULL, EOF, stdin, stdout, stderr,         */
  4.             /* fprintf(), fileno(), ... for standard i/o         */
  5.  
  6. extern int errno;
  7.  
  8. char  name[] = "CRYN - A data encryption system written in C, named files";
  9. char  version[] = "Version 6.00, 1992-11-15, 1400 hours";
  10. char  author[]  = "Copyright (c) 1987-1992 by author: Harry J. Smith";
  11. char  address[] =
  12.       "19628 Via Monte Dr., Saratoga, CA 95070.  All rights reserved.";
  13.  
  14. char  usage1[]  =  "usage: CRYN key [infile outfile [D]]";
  15. char  usage2[]  =  "  key only => Init CRY.CON file using key and exit";
  16. char  usage3[]  =  "      no D => Encipher and update CRY.CON file";
  17. char  usage4[]  =  "         D => Decipher";
  18.  
  19. #define  POOLSIZE 2048         /* Number of integers in random number pool */
  20. #define  CONSIZE  18         /* Number of characters in CRY.CON file       */
  21. #define  BUFSIZE  16384         /* Number of characters in file i/o buffer     */
  22. #define  MAXKEY   24         /* Number of characters in short key     */
  23. #define  TRUE     1
  24. #define  FALSE    0
  25.  
  26. int  ri[9],        /* Current random integers from the 9 generators     */
  27.      rs[9],        /* Initial random seeds for the 9 generators     */
  28.      rc[9],        /* Current value of clear continuation seeds     */
  29.      rr,        /* Random running combination of ri[0] thru ri[8]     */
  30.      *pool,        /* Pool of POOLSIZE random integers             */
  31.      encipher,        /* Boolean, Enciphering a file, FALSE => Deciphering */
  32.      next = 0,        /* Next random no. routine to use, cycles 0 thru 8     */
  33.      poolmask =        /* Mask for index to random pool = 2**N - 1         */
  34.        POOLSIZE-1;
  35. char *buf,        /* Buffer for file i/o                 */
  36.      key[MAXKEY+1]; /* The short key string in standard form         */
  37. FILE *infile,        /* File pointer of input file             */
  38.      *outfile,        /* File pointer of output file             */
  39.      *confile;        /* File pointer of continuation file "CRY.CON"     */
  40.  
  41. int  init( int argc, char *argv[]);  /* Initialize the process         */
  42. int  term( void);             /* Terminate processing         */
  43. void standard( char *cp);         /* Standardize a key string     */
  44. void convkey( void);             /* Convert key to 9 seeds         */
  45. int  rn( int n);             /* random integer from ri[n], n<9     */
  46. int  rc9( void);             /* Combination of rn(0) thru rn(8)     */
  47. void erase( void);             /* Erase all trace of the key     */
  48.  
  49. /* --------------------------------------------------------------------- */
  50. void main( int argc, char *argv[])
  51. {
  52.    int  *ip,            /* Pointer to current integer in buf     */
  53.     *jp,            /* Pointer after last integer in buf     */
  54.     ind,            /* Random index into pool of random integers */
  55.     nr,            /* Number of bytes read into buf         */
  56.     rc;            /* Return code from init() and term()     */
  57.  
  58.                       /* Validate arguments         */
  59.    if( !((argc == 2) || (argc == 4) ||
  60.     ((argc == 5) && ((*argv[4] == 'D') || (*argv[4] == 'd')))))
  61.    {
  62.       fprintf( stderr, "\n%s\n%s\n%s\n\n", name, version, author);
  63.       fprintf( stderr, "%s\n%s\n%s\n%s\n", usage1, usage2, usage3, usage4);
  64.       exit( 1);
  65.    }
  66.  
  67.    rc = init( argc, argv);          /* Initialize the process     */
  68.  
  69.    if( rc)                                /* If error in init or done    */
  70.    {  erase();                  /* erase key             */
  71.       exit( rc);              /* and exit             */
  72.    }
  73.                       /* Read input file         */
  74.  
  75.    while ( (nr = fread( buf, 1, BUFSIZE, infile)) > 0)
  76.    {
  77.       for( ip = (int *)buf, jp = ip + (nr+1)/2;   ip != jp;   ++ip)
  78.       {
  79.      /*
  80.       * This is the heart of the encryption method
  81.       */
  82.      ind = rr & poolmask;          /* Random index to random pool */
  83.      *ip ^= pool[ind];          /* XOR data with random int     */
  84.      pool[ind] ^= ( rr += rn( next)); /* XOR random int with next rr */
  85.      if( ++next == 9)          /* Cycle to next generator     */
  86.         next = 0;
  87.       }
  88.       if( fwrite( buf, 1, nr, outfile) != nr) /* Write output file     */
  89.       {                              /* If write error, exit     */
  90.      erase();
  91.      fprintf( stderr, "CRYN: write error no. %d\n", errno);
  92.      exit( 2);
  93.       }
  94.    }
  95.    rc = term();                  /* Terminate processing     */
  96.    erase();                  /* Erase all trace of the key     */
  97.    fprintf( stderr, "return = %d\n", rc); /* Diagnostic, may be removed     */
  98.    exit( rc);                  /* Exit main             */
  99. }                      /* End of main (CRYN)         */
  100.  
  101. /* --------------------------------------------------------------------- */
  102. int init( int argc, char *argv[])      /* Initialize the process     */
  103. {
  104.    /*  Initialize key etc.
  105.     *  Returns a non-zero flag if error
  106.     */
  107.  
  108.    int  i, j, len;
  109.    char *chp;
  110.  
  111.    buf  = malloc( BUFSIZE);          /* Allocate memory for arrays     */
  112.    pool = (int *) malloc( 2 * POOLSIZE);
  113.  
  114.    if( buf == (char *) NULL || pool == (int *) NULL)
  115.    {
  116.       fprintf( stderr, "CRYN: not enough memory\n");
  117.       return( 3);
  118.    }
  119.  
  120.    if( (infile = fopen( argv[1], "rt")) == NULL) /* Try to open key file */
  121.    {
  122.       strcpy(buf, argv[1]);
  123.       len = strlen( buf);
  124.       for( i = 0;  i < len;  ++i)
  125.      argv[1][i] = 0;          /* Erase input key         */
  126.    }
  127.    else
  128.    {
  129.       fgets( buf, 256, infile);
  130.       fclose( infile);
  131.       if( (chp = strchr( buf, '\n')) != NULL)
  132.      *chp = '\0';
  133.    }
  134.  
  135.    standard( buf);              /* Standardize long key     */
  136.  
  137.    fprintf( stderr, "%s = input key in standard form\n", buf);
  138.  
  139.    if( (len = strlen( buf)) > MAXKEY)
  140.    {
  141.       for( i = 1; i < MAXKEY; ++i)      /* Hash long key         */
  142.      buf[i] += buf[i-1];
  143.       for( i = len-2; i >= MAXKEY; --i)
  144.      buf[i] += buf[i+1];
  145.    }
  146.  
  147.    for( i = 0;  i <= MAXKEY;  ++i)      /* Clear short key         */
  148.       key[i] = 0;
  149.  
  150.    for( i = j = 0;  i < len;  ++i)      /* Compress long key         */
  151.    {
  152.       key[j] += buf[i];
  153.       buf[i] = 0;              /* Erase input key         */
  154.       if( ++j == MAXKEY)
  155.      j = 0;
  156.    }
  157.  
  158.    for( i = 0;  i < MAXKEY;  ++i)      /* Fill out key replacing     */
  159.       if( !key[i])              /* nulls with spaces         */
  160.      key[i] = ' ';
  161.  
  162.    standard( key);              /* Standardize short key     */
  163.    convkey();                  /* Convert short key to random */
  164.                       /* number seeds         */
  165.  
  166.    if( argc == 2)              /* If only key given         */
  167.    {
  168.       if( (confile = fopen( "CRY.CON", "wb")) == NULL)
  169.       {
  170.      fprintf( stderr,
  171.         "CRYN: cannot open CRY.CON, error no. %d\n", errno);
  172.      return( 4);
  173.       }
  174.       for( i = 0;  i < 9;  ++i)           /* Initialize CRY.CON file     */
  175.      ri[i] = rs[i];
  176.  
  177.       for( i = POOLSIZE-1;  i >= 0;  --i) /* Build a random record     */
  178.      pool[i] = rc9();
  179.  
  180.                       /* Write continuation file     */
  181.  
  182.       if( fwrite( pool, 1, CONSIZE, confile) != CONSIZE)
  183.       {
  184.      fprintf( stderr,
  185.         "CRYN: cannot write CRY.CON, error no. %d\n", errno);
  186.      return( 5);
  187.       }
  188.       fclose( confile);
  189.       fprintf( stderr, "Continuation file CRY.CON updated\n");
  190.       return( 6);
  191.    }
  192.                       /* If file names given     */
  193.  
  194.    if( (infile = fopen( argv[2], "rb")) == NULL) /* Open input file      */
  195.    {
  196.       fprintf( stderr,
  197.      "CRYN: cannot open %s error no. %d\n", argv[2], errno);
  198.       return( 7);
  199.    }
  200.    if( (outfile = fopen( argv[3], "wb")) == NULL) /* Open output file    */
  201.    {
  202.       fprintf( stderr,
  203.      "CRYN: cannot open %s error no. %d\n", argv[3], errno);
  204.       return( 8);
  205.    }
  206.  
  207.    encipher = (argc == 4);          /* Set encipher/decipher flag     */
  208.  
  209.    if( encipher)              /* If encipher, open con. file */
  210.    {
  211.       if( (confile = fopen( "CRY.CON", "rb")) == NULL)
  212.       {
  213.      fprintf( stderr,
  214.         "CRYN: cannot open CRY.CON, error no. %d\n", errno);
  215.      return( 9);
  216.       }
  217.                       /* Read continuation file     */
  218.  
  219.       if( fread( pool, 1, CONSIZE, confile) != CONSIZE)
  220.       {
  221.      fprintf( stderr,
  222.         "CRYN: cannot read CRY.CON, error no. %d\n", errno);
  223.      return( 10);
  224.       }
  225.       fclose( confile);
  226.                       /* Write 1st record of outfile */
  227.  
  228.       if( fwrite( pool, 1, CONSIZE, outfile) != CONSIZE)
  229.       {
  230.      fprintf( stderr, "CRYN: write error no. %d\n", errno);
  231.      return( 11);
  232.       }
  233.    }
  234.    else                      /* Else decipher         */
  235.    {
  236.                       /* Read first record of file     */
  237.  
  238.       if( (i = fread( pool, 1, CONSIZE, infile)) != CONSIZE)
  239.       {
  240.      fprintf( stderr, "CRYN: read error no. %d\n", errno);
  241.      return( 12);
  242.       }
  243.    }
  244.  
  245.    for( i = 0;  i < 9;  ++i)          /* Save and encode         */
  246.    {                      /* continuation seeds         */
  247.       rc[i] = pool[i];
  248.       ri[i] = rs[i] ^ pool[i];
  249.       if( !ri[i])              /* Do not allow a zero seed     */
  250.      ri[i] = 1;
  251.    }
  252.    rr = rc9();                  /* Init first word of running     */
  253.                       /* combination of ri[0]- ri[8] */
  254.  
  255.    for( i = 0;  i < POOLSIZE;  ++i)      /* Initialize pool, random int */
  256.    {
  257.       pool[i] = rr += rn( next);
  258.       if( ++next == 9)
  259.      next = 0;
  260.    }
  261.    rr = rc9();                  /* Init rr for first random     */
  262.                       /* index into pool         */
  263.  
  264.    fprintf( stderr, "%s = short key in standard form\n", key);
  265.  
  266.    for( i = 0;  i < 9;  ++i)
  267.       fprintf( stderr, "rs[%d] = %-7d ", i, rs[i]);
  268.  
  269.    for( i = 0;  i < 9;  ++i)
  270.       fprintf( stderr, "ri[%d] = %-7d ", i, ri[i]);
  271.  
  272.    if( encipher)
  273.       fprintf( stderr, "\nEncipher\n");
  274.    else
  275.       fprintf( stderr, "\nDecipher\n");
  276.    return( 0);
  277. }                      /* End of init         */
  278.  
  279. /* --------------------------------------------------------------------- */
  280. int term( void)
  281. {
  282.    /*  Terminate processing
  283.     *  Returns a non-zero flag if error
  284.     */
  285.  
  286.    int  i;
  287.  
  288.    if( ferror( infile))                /* Test for infile read error     */
  289.    {
  290.       fprintf( stderr, "CRYN: read error no. %d\n", errno);
  291.       return( 13);
  292.    }
  293.  
  294.    fclose( infile);              /* Close files         */
  295.    fclose( outfile);
  296.  
  297.    if( encipher)              /* If encipher, open con. file */
  298.    {
  299.       if( (confile = fopen( "CRY.CON", "wb")) == NULL)
  300.       {
  301.      fprintf( stderr,
  302.         "CRYN: cannot open CRY.CON, error no. %d\n", errno);
  303.      return( 14);
  304.       }
  305.  
  306.       for( i = 0;  i < 9;  ++i)            /* Restore clear continuation     */
  307.      ri[i] = rc[i];              /* seeds             */
  308.  
  309.       for( i = POOLSIZE-1;  i >= 0;  --i) /* Build a random record     */
  310.      pool[i] = rc9();
  311.                       /* Write continuation file     */
  312.  
  313.       if( fwrite( pool, 1, CONSIZE, confile) != CONSIZE)
  314.       {
  315.      fprintf( stderr,
  316.         "CRYN: cannot write CRY.CON, error no. %d\n", errno);
  317.      return( 15);
  318.       }
  319.       fclose( confile);
  320.    }
  321.    return( 0);
  322. }                      /* End of term         */
  323.  
  324. /* --------------------------------------------------------------------- */
  325. void standard( char *cp)
  326. {
  327.    /*  Standardize a key string
  328.     *  Output characters are from 33 to 95 inclusive
  329.     */
  330.  
  331.    for(  ;  *cp;  ++cp)
  332.    {
  333.       *cp &= 127;
  334.  
  335.       if( *cp > 95)
  336.       *cp -= 32;
  337.  
  338.       if( *cp < 32)
  339.       *cp += 32;
  340.  
  341.       if( *cp == ' ')
  342.       *cp = '/';
  343.    }
  344. }                      /* End of standard         */
  345.  
  346. /* --------------------------------------------------------------------- */
  347. void convkey( void)
  348. {
  349.    /*  Convert the encryption key to 9 seeds
  350.     *
  351.     *  input: key[i], i = 0, ..., MAXKEY-1
  352.     *  output: rs[j], j = 0, ..., 8
  353.     *
  354.     *    [0]    [1]    [2]    [3]    [4]    [5]    [6]   ...  [22]   [23]
  355.     *  111111 111111 111111 111111 111111 111111 111111      111111 111111
  356.     *     6      6     4  2    6      6    2  4     6        6      6
  357.     *  ****** seed0 *****...... seed1 ......***** seed2  ...  seed8 ******
  358.     *         16 BITS           16 BITS         16 BITS     16 BITS
  359.     *
  360.     *  144 bit key converted to 144 bits of seed,
  361.     *  seeds of zero are changed to 1.
  362.     */
  363.  
  364.    int  i, j,
  365.     keyi[MAXKEY];         /* Key in integer form, 6 bits each int */
  366.  
  367.    for( i = 0;  i < MAXKEY;  ++i)
  368.       keyi[i] = key[i] & 63;
  369.  
  370.    for( i = 0, j = 0;  j < 9;  i += 8, j += 3)
  371.    {
  372.       rs[j]   =  ( keyi[i]   << 10) |
  373.          ( keyi[i+1] <<  4) |
  374.          ( keyi[i+2] >>  2);
  375.  
  376.       rs[j+1] =  ( keyi[i+2] << 14) |
  377.          ( keyi[i+3] <<  8) |
  378.          ( keyi[i+4] <<  2) |
  379.          ( keyi[i+5] >>  4);
  380.  
  381.       rs[j+2] =  ( keyi[i+5] << 12) |
  382.          ( keyi[i+6] <<  6) |
  383.            keyi[i+7];
  384.    }
  385.    for( j = 0;  j < 9;  ++j)          /* Do not allow a zero seed     */
  386.       if( !rs[j])
  387.      rs[j] = 1;
  388.  
  389.    for( i = 0;  i < MAXKEY;  ++i)
  390.       keyi[i] = 0;              /* Erase local key         */
  391. }                      /* End of convkey         */
  392.  
  393. /* --------------------------------------------------------------------- */
  394. int rn( int n)
  395. {
  396.    /*
  397.     *  Returns the next random integer from ri[n], 0 <= n <= 8
  398.     */
  399.  
  400.    static int  repeat = TRUE;
  401.    int  i;
  402.  
  403.    switch( n)
  404.    {
  405.    case 0:
  406.  
  407.      /*  1st Congruential Generator, 16 bits
  408.       *  Generates Random integers from -32768 to 32767 inclusive
  409.       *  Cycle length = 65536 = 2**16
  410.       */
  411.  
  412.       return( ri[0] = 25173 * ri[0] + 6925);
  413.  
  414.    case 1:
  415.  
  416.      /*  1st Shift-register Generator, 16 bits
  417.       *  Random integer from -32768 to 32767 inclusive, 0 not generated
  418.       *  Generator = -22620, Cycle length = 65535 = 3 * 5 * 17 * 257
  419.       */
  420.  
  421.       if( ri[1] & 1)
  422.          return( ri[1] = ( (unsigned) ri[1] >> 1) ^ -22620);
  423.  
  424.       return( (unsigned) ri[1] >>= 1);
  425.  
  426.    case 2:
  427.  
  428.      /*  2nd Congruential Generator, 16 bits
  429.       *  Random integer from -32768 to 32767 inclusive
  430.       *  Cycle length = 65537 = prime, zero repeats once
  431.       */
  432.  
  433.       if( !ri[2])
  434.       {
  435.          if( repeat)
  436.          {
  437.         repeat = FALSE;
  438.         return( 0);
  439.          }
  440.          else repeat = TRUE;
  441.       }
  442.  
  443.       return( ri[2] = 23629 * ri[2] + 13849);
  444.  
  445.    case 3:
  446.  
  447.      /*  2nd Shift-register Generator, 16 bits
  448.       *  Random integer from -32768 to 32767, not all generated
  449.       *  Generator = -07493, Cycle length = 65521 = prime, (65536 - 15)
  450.       */
  451.  
  452.       if( ri[3] & 1)
  453.          ri[3] = ( (unsigned) ri[3] >> 1) ^ -7493;
  454.       else
  455.          (unsigned) ri[3] >>= 1;
  456.  
  457.       if( ri[3] == 1)
  458.          for( i = 0;  i < 14;  ++i)
  459.         rn( 3);                  /* Throw 14 away         */
  460.  
  461.       return( ri[3]);
  462.  
  463.    case 4:
  464.  
  465.      /*  3rd Congruential Generator, 16 bits
  466.       *  Random integer from -32768 to 32767, not all generated
  467.       *  Cycle length = 65519 = prime, (65536 - 17)
  468.       */
  469.  
  470.       ri[4] = 4821 * ri[4] + 13001;
  471.       if( !ri[4])
  472.          for( i = 0;  i < 17;  ++i)
  473.         rn( 4);                /* Throw 17 away         */
  474.  
  475.       return( ri[4]);
  476.  
  477.    case 5:
  478.  
  479.      /*  3rd Shift-register Generator, 16 bits
  480.       *  Random integer from -32768 to 32767, not all generated
  481.       *  Generator = -25501, Cycle length = 65497 = prime, (65536 - 39)
  482.       */
  483.  
  484.       if( ri[5] & 1)
  485.          ri[5] = ( (unsigned) ri[5] >> 1) ^ -25501;
  486.       else
  487.          (unsigned) ri[5] >>= 1;
  488.  
  489.       if( ri[5] == 1)
  490.          for( i = 0;  i < 38;  ++i)
  491.         rn( 5);                /* Throw 38 away         */
  492.  
  493.       return( ri[5]);
  494.  
  495.    case 6:
  496.  
  497.      /*  4th Congruential Generator, 16 bits
  498.       *  Random integer from -32768 to 32767, not all generated
  499.       *  Cycle length = 65479 = prime, (65536 - 57)
  500.       */
  501.  
  502.       ri[6] = 10349 * ri[6] + 7001;
  503.       if( !ri[6])
  504.          for( i = 0;  i < 57;  ++i)
  505.         rn( 6);                /* Throw 57 away         */
  506.  
  507.       return( ri[6]);
  508.  
  509.    case 7:
  510.  
  511.      /*  4th Shift-register Generator, 16 bits
  512.       *  Random integer from -32768 to 32767, not all generated
  513.       *  Generator = -18916, Cycle length = 65449 = prime, (65536 - 87)
  514.       */
  515.  
  516.       if( ri[7] & 1)
  517.          ri[7] = ( (unsigned) ri[7] >> 1) ^ -18916;
  518.       else
  519.          (unsigned) ri[7] >>= 1;
  520.  
  521.       if( ri[7] == 1)
  522.          for( i = 0;  i < 86;  ++i)
  523.         rn( 7);                /* Throw 86 away         */
  524.  
  525.       return( ri[7]);
  526.  
  527.    case 8:
  528.  
  529.      /*  5th Congruential Generator, 16 bits
  530.       *  Random integer from -32768 to 32767, not all generated
  531.       *  Cycle length = 65447 = prime, (65536 - 89)
  532.       */
  533.  
  534.       ri[8] = 30133 * ri[8] + 14001;
  535.       if( !ri[8])
  536.          for( i = 0;  i < 89;  ++i)
  537.         rn( 8);                /* Throw 89 away         */
  538.  
  539.       return( ri[8]);
  540.    }
  541.    return( 0);                            /* This line is never reached  */
  542. }                      /* End of rn             */
  543.  
  544. /* --------------------------------------------------------------------- */
  545. int rc9( void)
  546. {
  547.    /*
  548.     *  Combination of rn(0) thru rn(8), one each
  549.     */
  550.  
  551.    int  i,  rc;
  552.  
  553.    for( rc = 0, i = 0;  i < 9;  ++i)
  554.       rc += rn( i);
  555.  
  556.    return( rc);
  557. }                      /* End of rc9             */
  558.  
  559. /* --------------------------------------------------------------------- */
  560. void erase( void)
  561. {
  562.    /*
  563.     *  Erase all trace of the encryption key
  564.     */
  565.  
  566.    int  i;
  567.  
  568.    for( i = 0;  i < MAXKEY;  ++i)
  569.       key[i] = 0;
  570.  
  571.    for( i = 0;  i < 9;  ++i)
  572.       ri[i] = rs[i] = 0;
  573.  
  574.    for( i = 0;  i < POOLSIZE;  ++i)
  575.       pool[i] = 0;
  576.  
  577.    rr = 0;
  578. }                      /* End of erase         */
  579.                       /* End of CRYN.C         */
  580.